package org.lgiavedoni.android.franq.util.service;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.io.StringBufferInputStream;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;

import org.lgiavedoni.android.franq.core.service.Service;
import org.lgiavedoni.android.franq.service.log.Logger;
import org.lgiavedoni.android.franq.util.JSONUtil;
import org.w3c.dom.Document;
import org.w3c.dom.NodeList;

public class ServiceUtil {

	static final String IMPLEMENTATION = "implementation";

	public static class Implementation {
		private final String clazz;

		public Implementation(String clazz) {
			this.clazz = clazz;
		}

		public String getClazz() {
			return clazz;
		}
	}

	public static List<Implementation> getImplementations(String s) {
		return getImplementations(new StringBufferInputStream(s));
	}

	public static List<Implementation> getImplementations(File f) {
		try {
			return getImplementations(new FileInputStream(f));
		} catch (FileNotFoundException e) {
			Logger.inst.error(e);
		}
		return new ArrayList<Implementation>();
	}

	public static List<Implementation> getImplementations(InputStream is) {
		final List<Implementation> messages = new ArrayList<Implementation>();
		try {

			DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
			DocumentBuilder db = dbf.newDocumentBuilder();
			Document doc = db.parse(is);
			doc.getDocumentElement().normalize();
			NodeList nodeLst = doc.getElementsByTagName(IMPLEMENTATION);

			for (int s = 0; s < nodeLst.getLength(); s++) {
				// messages.add(new
				// ServiceUtil.Implementation((nodeLst.item(s)).getTextContent()));
				messages.add(new ServiceUtil.Implementation(JSONUtil.getTextContent(nodeLst.item(s))));
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		return messages;
	}

	public static void main(String a[]) {

		String xml = "" + //
				"<?xml version=\"1.0\" encoding=\"UTF-8\"?>" + //
				"<service>" + //
				"<implementations>" + //
				"<implementation>" + //
				"aaaa" + //
				"</implementation>" + //
				"</implementations>" + //
				"</service>";

		System.out.println(new ServiceUtil().getImplementations(xml));
	}

	public static Collection<Object> initialize(List<Implementation> list) {
		List<Object> result = new ArrayList<Object>();
		for (Implementation imp : list) {
			try {
				// Get the class
				Class clazz = Class.forName(imp.getClazz());
				if (getInstance(clazz) != null) {
					result.add(getInstance(clazz));
				} else {
					Object classInstance = clazz.newInstance();
					if (classInstance instanceof Service)
						Logger.inst.error("The service: [" + imp.getClazz() + "] don't have the inst attribute! ");
					result.add(classInstance);

				}
			} catch (Exception e) {
				Logger.inst.error(e);
			}
		}
		return result;

	}

	private static Object getInstance(Class clazz) {
		for (Field field : clazz.getDeclaredFields()) {
			if (field.getName().equals("inst") && field.getDeclaringClass().equals(clazz)) {
				try {
					return field.get(null);
				} catch (Exception e) {
				}
			}
		}
		return null;
	}

}
